package sample.sharding;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.shardingsphere.api.hint.HintManager;
import org.apache.shardingsphere.api.sharding.hint.HintShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.hint.HintShardingValue;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

/**
 * @date 2020/8/28
 */
@SpringBootApplication
public class ShardingSample {

	public static void main(String[] args) {
		System.out.println(null instanceof Long);
		SpringApplication.run(ShardingSample.class, args);
	}

	//@Component
	public class ShardingRunner implements CommandLineRunner {

		@Autowired
		private JdbcTemplate jdbcTemplate;

		public void run(String... args) throws Exception {
			HintManager hintManager = HintManager.getInstance();
			hintManager.addTableShardingValue("batch_job_instance", 1);
			List<Map<String, Object>> maps = jdbcTemplate
					.queryForList("select * from batch_job_instance where job_name='a' ");

			System.out.println(maps);
		}
	}

	//@Component
	public class HintRunner implements CommandLineRunner {

		@Autowired
		private JdbcTemplate jdbcTemplate;

		public void run(String... args) throws Exception {
			HintManager hintManager = HintManager.getInstance();
			hintManager.addTableShardingValue("batch_job_instance", 1);
			hintManager.addTableShardingValue("batch_job_instance", 2);

			List<Map<String, Object>> maps = jdbcTemplate
					.queryForList("select * from batch_job_instance where job_name='a' "
							+ "and job_instance_id in (select max(job_instance_id) from batch_job_instance where job_name='a')");
			hintManager.close();
			System.out.println(maps);
		}
	}


	@Component
	public class HintBatchRunner implements CommandLineRunner {

		@Autowired
		private JdbcTemplate jdbcTemplate;

		public void run(String... args) throws Exception {

			List<Object[]> list = new ArrayList<>();
			list.add(new Object[] {1000L,0L,"job1000","a", new Date()});
			list.add(new Object[] {1001L,0L,"job1001","a", new Date()});
			//int[] types = new int[] {Types.BIGINT, Types.BIGINT, Types.VARCHAR, Types.VARCHAR, Types.TIMESTAMP};
			//int[] res = jdbcTemplate.batchUpdate("insert into batch_job_instance values (?,?,?,?,?)",  list, types);
			jdbcTemplate.batchUpdate("insert into batch_job_instance values (?,?,?,?,?)", new BatchPreparedStatementSetter() {
				@Override
				public void setValues(PreparedStatement preparedStatement, int i) throws SQLException {
					preparedStatement.setLong(1, (Long) list.get(i)[0]);
					preparedStatement.setLong(2, (Long) list.get(i)[1]);
					preparedStatement.setString(3, (String) list.get(i)[2]);
					preparedStatement.setString(4, (String) list.get(i)[3]);
					preparedStatement.setTimestamp(5, new Timestamp(((Date)(list.get(i)[4])).getTime()));

					HintManager.clear();
					if (i == 0) {
						HintManager.getInstance().addTableShardingValue("batch_job_instance", "batch_job_instance_1");
					} else {
						HintManager.getInstance().addTableShardingValue("batch_job_instance", "batch_job_instance_2");
					}
				}

				@Override
				public int getBatchSize() {
					return list.size();
				}
			});
		}
	}

	//@Component
	public class MaxRunner implements CommandLineRunner {
		@Autowired
		private JdbcTemplate jdbcTemplate;

		@Override
		public void run(String... args) throws Exception {
			Long maps = jdbcTemplate
					.queryForObject("select max(job_instance_id) from batch_job_instance where job_name=?",
							new Object[] {"jobA"}, Long.class);
			System.out.println(maps);
		}
	}
}
